import UIKit
/**
 方法是与特定类型相关联的函数。在Swift中类，结构体，枚举都可以定义实例方法，也可定义类型方法。类型方法就是类似OC中的类方法。
 */

//实例方法。实例方法属于特定类，结构体或者枚举类型实例的方法。
class Count {
    var count = 0
    func increment() {
        count += 1
    }
    func increment(amount:Int) {
        count += amount
    }
    
    func reset() {
        count = 0
    }
}

let counter = Count()
counter.increment()
counter.increment(amount: 2)
counter.reset()
counter.count

//方法的局部参数名称和外部参数名称。与函数参数可以有一个局部名称（函数内使用）和一个外部名称（调用函数时使用)一样，方法参数也一样。

class Counter {
    var count = 0
    func incrementBy(amout: Int, times: Int){
        count += amout * times
    }
}

let counter1 = Counter()
counter1.incrementBy(amout: 1, times: 3)

//修改方法外部参数名称, 不想为第二参数提供外部参数用 _ 表示
class Counter2 {
    var count = 1
    func incrementBy(amout: Int, _ times:Int)  {
        count += amout * times
    }
}

let c2 = Counter2()
c2.incrementBy(amout: 1, 4)

//self属性  每个实例都有个隐含属性self,self就是指实例本身。一般情况下可以不写。但是有时候需要区分方法的参数和实例的属性重名的情况，需要用self区分。

//实例方法中修改值类型。结构体和枚举是值类型，一般，属性不能在它的实例方法修改。如果要修改，可以在方法前加mutating.
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX:Double, y deltaY:Double)  {
        x += deltaX
        y += deltaY
    }
}

var p = Point(x: 1, y:1)
p.moveByX(deltaX: 2, y: 4)
print("The point is now at \(p.x), \(p.y)")

//在mutating方法中给self赋值。
struct Point2 {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY:Double) {
        self = Point2(x: x + deltaX, y: y + deltaY)
    }
}

enum TriStateSwitch {
case Off, Low, High
    mutating func next() {
        switch self {
        case .Off:
            self = .Low
        case .Low:
            self = .High
        case .High:
            self = .Off
        }
    }
}

var overtLight = TriStateSwitch.Low
overtLight.next()
overtLight.next()
//类型方法，被类型本身调用.在类型方法结构体中，self指向类型本身，不是某个具体实例。
struct LevelTracker {
    static var highestUnlocedLevel = 1
    static func unlockLever(level: Int) {
        if level > highestUnlocedLevel {
            highestUnlocedLevel = level
        }
    }
    static func levelIsunLocked(level:Int) -> Bool {
        return level <= highestUnlocedLevel
    }
    var currentlevel = 1
    mutating func advanceToLevel(level:Int) -> Bool {
        if LevelTracker.levelIsunLocked(level: level) {
            currentlevel = level
            return true
        } else {
            return false
        }
    }
}

class Player {
    var tracker = LevelTracker()
    var palyerName: String = ""
    func completedLevel(level:Int) {
        LevelTracker.unlockLever(level: level + 1)
        tracker.advanceToLevel(level: level + 1)
    }
    init(name: String) {
       palyerName = name
    }
}

var player = Player(name: "Ann")
player.completedLevel(level: 1)

player = Player(name: "jone")
if player.tracker.advanceToLevel(level: 6) {
    print("player is now on level 6")
} else {
    print("player 6 has not yet been unlocked")
}
